#include "SQLCurrentTimeExpr.h"
#include "../visitor/SQLASTVisitor.h"
#include "../../Exception/NullPointerException.h"
#include "../../utils/StringUtils.h"
#include "../../utils/log.h"

SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::CURRENT_TIME = SQLCurrentTimeExpr_Type(make_string_ptr("CURRENT_TIME"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::CURRENT_DATE = SQLCurrentTimeExpr_Type(make_string_ptr("CURRENT_DATE"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::CURDATE = SQLCurrentTimeExpr_Type(make_string_ptr("CURDATE"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::CURTIME = SQLCurrentTimeExpr_Type(make_string_ptr("CURTIME"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::CURRENT_TIMESTAMP = SQLCurrentTimeExpr_Type(make_string_ptr("CURRENT_TIMESTAMP"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::LOCALTIME = SQLCurrentTimeExpr_Type(make_string_ptr("LOCALTIME"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::LOCALTIMESTAMP = SQLCurrentTimeExpr_Type(make_string_ptr("LOCALTIMESTAMP"));
SQLCurrentTimeExpr_Type SQLCurrentTimeExpr_Type::SYSDATE = SQLCurrentTimeExpr_Type(make_string_ptr("SYSDATE"));

SQLCurrentTimeExpr_Type::SQLCurrentTimeExpr_Type(string_ptr name_)
{
  this->name = name_;
  // this->nameLCase = name.toLowerCase();
  // std::transform(name->begin(), name->end(), std::back_inserter(this->nameLCase), [](unsigned char c)
  //                { return std::tolower(c); });
  // LOG_INFO << "name:" << name_->c_str();
  this->nameLCase = StringUtils::toLower(name_);
}

int SQLCurrentTimeExpr_Type::hashCode()
{
  return 0;
}

SQLCurrentTimeExpr::SQLCurrentTimeExpr(SQLCurrentTimeExpr_Type_ptr type)
{
  if (type == NULL)
  {
    throw new NullPointerException();
  }

  this->type = type;
}

void SQLCurrentTimeExpr::accept0(SQLASTVisitor_ptr v)
{
  v->visit(SharedObject(SQLCurrentTimeExpr));
  v->endVisit(SharedObject(SQLCurrentTimeExpr));
}

SQLCurrentTimeExpr_Type_ptr SQLCurrentTimeExpr::getType()
{
  return type;
}

bool SQLCurrentTimeExpr::equals(Object_ptr o)
{
  if (this == o.get())
  {
    return true;
  }
  if (getClass() != o->getClass())
  {
    return false;
  }

  std::shared_ptr<SQLCurrentTimeExpr> that = std::dynamic_pointer_cast<SQLCurrentTimeExpr>(o);

  return type == that->type;
}

int SQLCurrentTimeExpr::hashCode()
{
  return type->hashCode();
}

SQLObject_ptr SQLCurrentTimeExpr::clone()
{
  // return new SQLCurrentTimeExpr(type);
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLCurrentTimeExpr>(new SQLCurrentTimeExpr(type));
  std::shared_ptr<SQLCurrentTimeExpr> clone_res = std::dynamic_pointer_cast<SQLCurrentTimeExpr>(clone_tmp);

  return clone_res;
}
